#pragma once

#include "channel.h"
#include "dirs.hpp"
#include "force-dir.hpp"
#include "lines.hpp"
#include "tick.h"
#include "turn.hpp"
#include "types.h"
#include "wave.hpp"
#include "wfw.hpp"
#include "opportunity.hpp"
#include <cstdint>
#include <ctime>

namespace Trade {

struct Params
{
  dir_t dir_bear = 0;
  dir_t dir_ced = 0;
  dir_t dir_important_turn = 0;
  dir_t dir_turns_space = 0;
  dir_t dir_explicit = 0;
  dir_t dir_trend = 0;
  dir_t dir_rush = 0;
  dir_t dir_force = 0;
  dir_t dir_vision_with_space = 0;
  dir_t dir_vision = 0;
  dir_t old_vision = 0;
  dir_t pre_vision = 0;
  dir_t dir_big_needle = 0;
  dir_t dir_mda = 0;
  dir_t dir_virtual = 0;
  dir_t dir_opportunity = 0;
  dir_t d_dynamical = 0;
  dir_t d2_dynamical = 0;

  percent_t pct_oppo = 0;

  dir_t dir_tjm = 0;
  DIR_TYPE dt_dir_tjm = DIR_TYPE::UNKNOW;
  DIR_DREAMER_TYPE ddt_force = DIR_DREAMER_TYPE::DD_UNKNOW;

  reached_t reached_current_line = LIMIT_REACHED::REACHED_NONE;
  reached_t reached_golden_pnt = LIMIT_REACHED::REACHED_NONE;
  price_t hp_local_min = 0;
  price_t hp_local_max = 0;
  // price_t reverse_space = 0;

  time_t t_now_ = 0;
  event_t event = 0;
  int64_t idx__ = 0;

  Lines lines;
  // Lines better_lines;
  LinesGodenPnt lgp;
  Wave wave;
  StageDirs dirs;
  WaitingForWrong wfw;
  // Dir5 d5;
  NearFarTrend nft;
  // EnergyMark em_up;
  // EnergyMark em_dn;
  // PossibleDirChange pdc;
  // EnergyDir edir;
  Channels cl;
  MaxMinArray mma;
  MaDirArray mda;
  MaxMin mm_2h;
  IsBigNeedle bn;
  Opportunity oppor_trend;
  ForceLevel flv_79;
  // ForceDir fd;

  // DirList3 dd3_bd;
  // DirList3 dd3_pdc;
  // DirList3 dd3_em;
  // DirList3 dd3_ft;
  // DirList3 dd3_ced;
  DirList3 dd3_sd;
  DirList3 dd3_exp;
  DirList3 df3_near_79;
  DirList3 df3_far_79;
  DirList3 df3_near_rt;
  DirList3 df3_far_rt;
  DirList3 ds3_near;
  DirList3 ds3_far;
  // DirList3 dd3_vs;    // dir_vision_with_space
  // DirList3 dd3_force; // dir_force
  // DirList3 dd3_virtual;
  Turns5 ttttt;
  // ForceLists3 fl3;
  Force force; // read only

  PredictLine10 pls_up;
  PredictLine10 pls_dn;
  BigOppor10 bor;
  // Oppor10 os;
  Oppor10 os2;
  ForceSpot20 fs_near;
  ForceSpot20 fs_far;


  int read_data_(FILE* fp) noexcept;
  int show_params(const time_t t_now, const price_t hp_now) noexcept;

  time_t weak_timer___(const dir_t d) noexcept;
  time_t strong_timer___(const dir_t d) noexcept;
  time_t get_weak_timer___(const dir_t d) noexcept;
  time_t get_strong_timer___(const dir_t d) noexcept;

  time_t weak_timer(const dir_t d) noexcept;
  time_t strong_timer(const dir_t d) noexcept;
  time_t get_weak_timer(const dir_t d) noexcept;
  time_t get_strong_timer(const dir_t d) noexcept;
  time_t get_abs_weak_timer(const dir_t d) noexcept;
  time_t get_abs_strong_timer(const dir_t d) noexcept;

  price_t get_inflection(const dir_t d) const noexcept;

  bool have_4_force_dirs() const noexcept;
  dir_t get_rush_dir() const noexcept;
  bool is_consistent_dir(const dir_t d) const noexcept;
  bool big_same_near() const noexcept;

  int send_important_dirs() noexcept;
  int send_cur_pos() noexcept;

  bool space_opposite_tom(const dir_t d) const noexcept;
  DIR_DREAMER_TYPE retrive_vision_dir_type() const noexcept;

  dir_t predicted_near_dir() const noexcept;
  dir_t predicted_far_dir() const noexcept;
  dir_t force_near_dir() const noexcept;
  dir_t force_far_dir() const noexcept;
  dir_t get_mda_dir() const noexcept;
  void get_mda_percent(int& up, int& dn) const noexcept;

  bool confused_predict_near_or_far() const noexcept;
  bool consistent_visual_dir(const dir_t d) const noexcept;
  bool dangerous_dir(const dir_t d) const noexcept;

  int read_force(FILE* fp) noexcept;
};

struct ParamsMem
{
  ~ParamsMem() {}

  int64_t size = 0;
  Params* vo_data = nullptr;

  Params* vo_ = nullptr;
  int64_t idx = 0;
  time_t t_now = 0;
  price_t hp_now = 0;

  void data_idx(const int64_t idx, const price_t hp_now) noexcept;
  int read_dump_file(const char* dum_filepath) noexcept;

  void release() noexcept;
  Params* get_data_by_index(const int64_t idx) const noexcept;

  void set_mem_data(const Params* vo, const int64_t vo_size) noexcept;

public:
  int64_t sidx = 0;
  int64_t eidx = 0;
};

const uint16_t SIZE_OF_ONE_BLOCK = 3675;

extern int
load_data_from_shared_memory(const char* mem_key,
                             TICK_DATA* td,
                             size_t* td_size,
                             Params** vo,
                             size_t* vo_size) noexcept;
extern int
release_shared_memory(const char* mem_key,
                      const void* data,
                      const size_t td_size,
                      const size_t vo_size);

extern Params*
get_vo_by_index(const Params* vo,
                const size_t size,
                const int64_t idx) noexcept;

} // namespace Trade